package org.liu.simpleTank;

import java.util.ArrayList;
import java.util.Iterator;

import org.liu.simpleTank.envElement.EnvFactory;

public class Map {
	Cell[] cells = new Cell[CONSTS.MH * CONSTS.MW];
	{ // init cells 
		for(int i = 0; i < CONSTS.MH; i++)
			for(int j = 0; j < CONSTS.MW; j++) {
			cells[i * CONSTS.MW + j] = new Cell(this, i, j);
		}
		// connects cells
		for(int i = 0; i < CONSTS.MH; i++) {
			for(int j = 0; j < CONSTS.MW; j++) {
				getCell(i, j).init(
						getCell(i - 1, j),
						getCell(i, j + 1),
						getCell(i + 1, j),
						getCell(i, j - 1));
			}
		}
	}
	public Map() {
		// place env elements
	}
	
	public void initEnv(int[] data) {
		int length = CONSTS.MW * CONSTS.MH;
		if(data.length < length)
			length = data.length;
		
		for(int i = 0; i < length; i++) {
			int type = data[i];
			if(type == CONSTS.NONE || type == CONSTS.GROUND || type == CONSTS.HOME)
				continue;
			EnvElement el = EnvFactory.create(type);
			int row = i / CONSTS.MW;
			int col = i - row * CONSTS.MW;
			placeElement(row, col, el);
		}
	}
	
	public Cell getCell(int row, int col) {
		if(row < 0 || row >= CONSTS.MH || col < 0 || col >= CONSTS.MW)
			return null;
		int idx = row * CONSTS.MW + col;
		return cells[idx];
	}
	
	// element attaching and add event handling
	
	public boolean placeElement(int row, int col, Element el) {
		if(col < 0 || col >= CONSTS.MW || row < 0 || row > CONSTS.MH)
			return false;
		el.addToMap(this, row, col);
		// emit an event
		added(el);
		return true;
	}
	
	public static class AddEvent extends java.util.EventObject {
		private Element el;
		public AddEvent(Object source, Element el) {
			super(source);
			this.el = el;
		}
		public Element getElement() {
			return el;
		}
	}
	
	public abstract static class AddedListener implements java.util.EventListener {
		public abstract void added(AddEvent e);
	}
	
	private ArrayList<AddedListener> addedListeners;
	{
		addedListeners = new ArrayList<Map.AddedListener>(4);
	}
	
	public void addAddedListener(AddedListener listener) {
		addedListeners.add(listener);
	}
	
	private void added(Element el) {
		Iterator<AddedListener> iter = addedListeners.iterator();
		while(iter.hasNext()) {
			iter.next().added(new AddEvent(this, el));
		}
	}
}
